package com.file_to_base64_to_file;

import java.io.*;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @ClassName: FileToBase64ToFile
 * @Author: Jack.Zhang
 * @link <a href = "mailto:zhangyue26@hikvision.com.cn">联系作者<a/>
 * @Description:
 * @Date: 2021-11-04
 */
public class FileToBase64ToFile {
    private final static String ENCODING = "UTF-8";

    public static void main(String[] args) throws Exception {
//        Set<File> lastFolder = getLastFolder(new File("E:\\333333333"));
//        String parentFolder = "E:\\TTTTTTTTTTT";
//        for (File file : lastFolder) {
//            String fileName = file.getName();
//            String folderPath = parentFolder + File.separator + fileName;
//            File targetFile = new File(folderPath);
//            for (File listFile : file.listFiles()) {
//                writeEncodeFileToFile(listFile, targetFile, ENCODING);
//            }
//        }

        readBase64ToFile(new File("E:\\TTTTTTTTTTT\\200801"),new File("E:\\yyyyyy"),"jpg");

    }

    private static Set<File> getLastFolder(File sourceFile) {
        if (!sourceFile.isDirectory())
            return new HashSet<>();
        List<File> files = Arrays.asList(sourceFile.listFiles());
        Set<File> list = new HashSet<>();
        for (File file : files) {
            if (isLastFolder(file)) {
                // 是最底层的文件夹
                list.add(file);
            } else {
                list.addAll(getLastFolder(file));
            }
        }
        return list;
    }

    /**
     * 判断当前File引用是否为最底层的文件夹
     * @param sourceFile
     * @return
     */
    private static boolean isLastFolder(File sourceFile) {
        if (sourceFile== null || sourceFile.isFile())
            return false;
        List<File> files = Arrays.asList(sourceFile.listFiles());
        for (File file : files) {
            if (file.isDirectory())
                return false;
        }
        return true;
    }

    /**
     * <p>
     *    将文件转为Base64编码。并将Base64码存储至输出文件中，输出文件格式、后缀名不限，输出文本文件中，每一行为一个文件
     * <p/>
     * @param sourceFile 需要转为Base64编码的源文件
     * @param targetFile 输出的文本文件
     * @param encoding  编码格式
     * @return void
     * @author Jack.Zhang 2021/11/4 15:34
     * @link <a href = "mailto:zhangyue26@hikvision.com.cn">联系作者<a/>
     * @since 1.0.0
     */
    public static void writeEncodeFileToFile(File sourceFile,File targetFile,String encoding) throws UnsupportedEncodingException {
        byte[] bytes = readFileToBase64(sourceFile);
        boolean flag = false;
        if (!targetFile.exists())
            flag = true;
        String encodingString = new String(Base64.getEncoder().encode(bytes), encoding);
        try (BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(targetFile,true));) {
            if (!flag)
                bufferedWriter.newLine();
            bufferedWriter.write(encodingString);
            bufferedWriter.flush();
        } catch (Exception e) {
            System.out.println("字节数组保存至文件时失败,源文件名称为："+sourceFile.getAbsolutePath());
            e.printStackTrace();
        }
    }

    private static byte[] readFileToBase64(File sourceFile) {
        try (FileInputStream inputStream = new FileInputStream(sourceFile);
             ByteArrayOutputStream bos = new ByteArrayOutputStream((int) sourceFile.length());) {
            byte[] bytes = new byte[8 * 1024];
            int len = -1;
            while ((len = inputStream.read(bytes)) != -1) {
                bos.write(bytes, 0, len);
                len = -1;
            }
            return bos.toByteArray();
        } catch (IOException e) {
            System.out.println("读取文件至字节数组失败");
        }
        return new byte[]{};
    }


    /**
     * <p>
     *    将base64文件中存储的文件编码转为文件
     * <p/>
     * @param base64File 存储base64编码的文本文件
     * @param destinationFolder 输出目标文件所存储文件夹
     * @param encoding 编码，置空即可
     * @param suffix  输出文件后缀名
     * @return void
     * @author Jack.Zhang 2021/11/4 15:52
     * @link <a href = "mailto:zhangyue26@hikvision.com.cn">联系作者<a/>
     * @since 1.0.0
     */
    public static void base64ToFile(File base64File,File destinationFolder,String encoding,String suffix) {
        if (!destinationFolder.isDirectory())
            throw new IllegalArgumentException("非文件夹类型");
        AtomicInteger success = new AtomicInteger();
        try (BufferedReader bufferedReader = new BufferedReader(new FileReader(base64File));) {
            Stream<String> lines = bufferedReader.lines();
            List<String> collect = lines.collect(Collectors.toList());
            System.out.println("总共"+collect.size()+"个文件");
            collect.forEach(base64String -> {
                        String fileName = System.currentTimeMillis() + "." + suffix;
                        byte[] decode = Base64.getDecoder().decode(base64String.getBytes());
                        File file = new File(destinationFolder, fileName);
                        try (FileOutputStream fileOutputStream = new FileOutputStream(file);) {
                            fileOutputStream.write(decode);
                            fileOutputStream.flush();
                            success.getAndIncrement();
                        } catch (Exception e) {
                            System.out.println("文件读取失败");
                        }
                    });
            System.out.println("完成"+success.get()+"文件读取");
        } catch (Exception e) {
            System.out.println("读取base64文件至文件夹时失败" + e.getLocalizedMessage());
            e.printStackTrace();
        }
    }

    /**
     *
     * @param sourceFile
     * @param targetFolder
     * @param targetSuffix
     */
    public static void readBase64ToFile(File sourceFile, File targetFolder,String targetSuffix) {
        if (sourceFile == null || sourceFile.isDirectory()
                || targetFolder == null || !targetFolder.isDirectory())
            throw new IllegalArgumentException("源文件或目标文件夹类型错误");
        try (FileReader fileReader = new FileReader(sourceFile);
             BufferedReader bufferedReader = new BufferedReader(fileReader);){
            File folder = new File(targetFolder.getAbsolutePath() + File.separator + sourceFile.getName());
            if (!folder.exists())
                folder.mkdirs();
            bufferedReader.lines().forEach(line->{
                byte[] fileBytes = Base64.getDecoder().decode(line);
                try (FileOutputStream fileOutputStream =
                             new FileOutputStream(folder.getAbsolutePath() + File.separator + System.nanoTime() + "." + targetSuffix)) {
                    fileOutputStream.write(fileBytes);
                    fileOutputStream.flush();
                } catch (Exception e) {
                    System.out.println("文件读取错误");
                }
            });
        } catch (Exception e) {
            System.out.println("Base64源文件读取错误" + sourceFile.getAbsolutePath());
        }
    }

}
